﻿using System;
using System.Collections.Generic;
using System.Text;
using Kugar.Core.BaseStruct;
using Kugar.Core.ExtMethod;
using System.ServiceModel.Channels;

namespace Kugar.Core.Communications.Transfer
{
    internal class RUDPSendDataSegmentPool:RecyclablePool<RUDPSendDataSegment>
    {
        private BufferManager _bufferManager = null;

        public RUDPSendDataSegmentPool(int maxLength, int minLength, BufferManager bufferManager)
            : base(maxLength, minLength)
        {
            _bufferManager=bufferManager;

            base.Init();
        }

        #region Overrides of RecyclablePool<RUDPSendDataSegment>

        /// <summary>
        ///     构建一个新的对象,该函数必须由继承的类实现
        /// </summary>
        /// <returns></returns>
        protected override RUDPSendDataSegment CreateRecyclableObject()
        {
            return new RUDPSendDataSegment(this, _bufferManager);
        }

        #endregion
    }

    internal class RUDPSendDataSegment : IEquatable<RUDPSendDataSegment>,IRecyclable
    {
        public int BagID;
        public short FragmentIndex;
        public byte[] Data;
        public int Offset;
        public int Count;
        public bool IsSuccess;
        public DateTime? SendTime;
        public bool IsLastFragment;
        public byte SendedCount;
        public int ConnectID;
        public short TotalLength;
        private RUDPSendDataSegmentPool _pool = null;
        private BufferManager _bufferManager = null;

        public RUDPSendDataSegment(RUDPSendDataSegmentPool pool,BufferManager bufferManager)
        {
            _pool = pool;
            _bufferManager = bufferManager;
        }

        public void Load(int connectID, int bagId, short fragmentIndex, byte[] data, int offset, int segmentCount, int bagTotalLength)
        {
            BagID = bagId;
            FragmentIndex = fragmentIndex;
            Data = data;
            Offset = offset;
            Count = segmentCount;
            IsLastFragment = false;
            ConnectID = connectID;
            TotalLength = (short)bagTotalLength;
        }

        public ArraySegment<byte> BuildToBytes()
        {
            var t=_bufferManager.TakeBuffer(13 + Count);

            //var buff = new byte[13 + Count];
            var bs = new ByteStream(t);

            bs.WriteByte(0x01);

            bs.WriteByte((byte)RUDPCmd.Data);

            bs.Write(ConnectID);
            bs.Write(BitConverter.GetBytes(FragmentIndex));
            bs.Write(BitConverter.GetBytes(TotalLength));

            bs.WriteByte(IsLastFragment ? (byte)1 : (byte)0);

            bs.Write(Data, Offset, Count);

            bs.Write(t.GetCRCCode(0, 11 + Count));

            bs.Dispose();

            return new ArraySegment<byte>(t, 0, 13 + Count);
        }

        public bool Equals(RUDPSendDataSegment other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            return other.BagID == BagID && other.FragmentIndex == FragmentIndex && other.ConnectID == ConnectID;
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != typeof(RUDPSendDataSegment)) return false;
            return Equals((RUDPSendDataSegment)obj);
        }

        public override int GetHashCode()
        {
            unchecked
            {
                int result = BagID;
                result = (result * 397) ^ FragmentIndex;
                result = (result * 397) ^ ConnectID;
                return result;
            }
        }

        public void Dispose()
        {
            BagID=-1;
            FragmentIndex = -1;
            Data=null;
            Offset=0;
            Count=0;
            IsSuccess=false;
            SendTime = null;
            IsLastFragment = false;
            SendedCount=0;
            ConnectID=-1;
            TotalLength=0;

            _pool.RecycleObject(this);

        }

        public static bool operator ==(RUDPSendDataSegment left, RUDPSendDataSegment right)
        {
            return Equals(left, right);
        }

        public static bool operator !=(RUDPSendDataSegment left, RUDPSendDataSegment right)
        {
            return !Equals(left, right);
        }

        #region Implementation of IRecyclable

        public IRecyclablePool<IRecyclable> Pool
        {
            get { throw new NotImplementedException(); }
            set { throw new NotImplementedException(); }
        }

        /// <summary>
        ///     当对象真正释放的时候，回收器会调用该函数
        /// </summary>
        public void DisposeObject()
        {
            BagID = -1;
            FragmentIndex = -1;
            Data = null;
            Offset = 0;
            Count = 0;
            IsSuccess = false;
            SendTime = null;
            IsLastFragment = false;
            SendedCount = 0;
            ConnectID = -1;
            TotalLength = 0;

            GC.SuppressFinalize(this);
        }

        #endregion
    }
}
